import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;


import de.tbmx.api.ClientAPI;
import de.tbmx.api.Order;
import de.tbmx.api.OrderListener;
import de.tbmx.api.Position;
import de.tbmx.api.PositionListener;
import de.tbmx.api.Quote;
import de.tbmx.api.QuoteListener;


public class OrderManager extends AbstractTableModel implements PositionListener{
	public static final int TABLE_COLUMN_COUNT = 24;
	public static final int HEDGE_POSITION = 23;
	public static final int BASE_POSITION = 22;
	public static final int IS_TRADE_PHASE = 21;
	public static final int NA_ONOFF  = 20;
	public static final int BA_ONOFF = 19;
	public static final int TICK_STOP = 18;
	public static final int AUCTION_OFFSET = 17;
	public static final int AUCTION_TIME = 16;
	public static final int IS_IN_AUCTION = 15;
	public static final int DELETE = 14;
	public static final int ON_OFF = 13;
	public static final int HEDGE_STATE = 12;
	public static final int BASE_STATE = 11;
	public static final int HIGH_SPREAD = 10;
	public static final int LOW_SPREAD = 9;
	public static final int MIN_STOCK_SIZE = 8;
	public static final int HEDGE_DIFF = 7;
	public static final int HEDGE_SIZE = 6;
	public static final int HEDGE_EXCHANGE = 5;
	public static final int HEDGE_SYM = 4;
	public static final int BASE_DIFF = 3;
	public static final int BASE_SIZE = 2;
	public static final int EXCHANGE = 1;
	public static final int BASE_SYM = 0;
	Vector<OrderInfo> m_allData = new Vector();
	HashMap<String, OrderInfo> m_symMap = new HashMap<String, OrderInfo> ();
//	HashMap<String, OrderInfo> m_BaseOrderMap = new HashMap<String, OrderInfo>();
//	HashMap<String, OrderInfo> m_HedgeOrderMap = new HashMap<String, OrderInfo>();
	/*
	Class type[] = new Class[] {
			String.class, String.class,String.class,String.class,String.class,
			String.class, String.class, String.class,String.class,String.class,
			Boolean.class, Boolean.class
	};
	*/
	private TextPanel m_log;
//	private ClientAPI client;
	
	@Override
	public int getColumnCount() {
		// TODO Auto-generated method stub
		return TABLE_COLUMN_COUNT;
	}

	@Override
	public int getRowCount() {
		// TODO Auto-generated method stub
		return m_allData.size();
	}

	@Override
	public Object getValueAt(int arg0, int arg1) {
		// TODO Auto-generated method stub
		return ((OrderInfo)m_allData.get(arg0)).getValue(arg1);
	}
	
	public void setValueAt(Object v, int row, int col){
		OrderInfo o = m_allData.get(row);
        switch(col) {
        case OrderManager.BASE_SIZE:
        	if (o.m_activate) { 
        		if (m_log != null) {
        			m_log.add("Min size can only change in inactive status! Please OFF the spreader first");
        		}
        	} else {   
        		o.m_size = Integer.parseInt(v.toString()); 
        	}
        	break;
        case OrderManager.HEDGE_SIZE:
        	if (o.m_activate) { 
        		if (m_log != null) {
        			m_log.add("Min size can only change in inactive status! Please OFF the spreader first");
        		}
        	} else {   
        		o.m_hedgeSize = Integer.parseInt(v.toString()); 
        	}
        	break;
        case OrderManager.MIN_STOCK_SIZE: 
        	if (o.m_activate) { 
        		if (m_log != null) {
        			m_log.add("Min size can only change in inactive status! Please OFF the spreader first");
        		}
        	} else {      		
        		o.m_minStockSize = Integer.parseInt(v.toString()); 
          	}
        	break;
        case OrderManager.LOW_SPREAD:
        	if (o.m_activate) { 
        		if (m_log != null) {
        			m_log.add("Spread level can only change in inactive status! Please OFF the spreader first");
        		}
        	} else {      		
        		o.m_lowSpread = Double.parseDouble(v.toString());
          	}
           	break;
        case OrderManager.HIGH_SPREAD:
        	if (o.m_activate) {
        		if (m_log != null) {
        			m_log.add("Spread level can only change in inactive status! Please OFF the spreader first");
        		}
        	} else {
        		o.m_highLpread = Double.parseDouble(v.toString());
        	}
        	break;
		case OrderManager.ON_OFF:
			if (v.equals(Boolean.TRUE)) {
				o.activateOrder();
			} else  {
				o.deactivateOrder();
			}			
			break;
		case OrderManager.DELETE:
			if (v.equals(Boolean.TRUE)) {
				/*
				String key = o.m_symbol + "." + o.m_exchange;
				if (m_BaseOrderMap.containsKey(key)) {
					m_BaseOrderMap.remove(key);
				}
				key = o.m_hedgeSymbol + "." + o.m_hedgeExchange;
				if (m_HedgeOrderMap.containsKey(key)) {
					m_HedgeOrderMap.remove(key);
				}
				*/
				o.m_delete = true;
				m_symMap.remove(o.m_symbol);
				m_symMap.remove(o.m_hedgeSymbol);
				m_allData.remove(row);
			}
			break;
		case TICK_STOP:
			if (o.m_activate) {
        		if (m_log != null) {
        			m_log.add("Tick ON/OFF can only change in inactive status! Please OFF the spreader first");
        		}
        	} else {
           		if (o.m_isInAuction && v.equals(Boolean.TRUE)) {
        			m_log.add("Tick ON/OFF can't be enabled during auction time");
        		} else {
        			o.m_tickOnOff =(Boolean) v;
        		}
        	}
			break;
		case BA_ONOFF:
			if (o.m_activate) {
        		if (m_log != null) {
        			m_log.add("b=a ON/OFF can only change in inactive status! Please OFF the spreader first");
        		}
        	} else {
           		if (o.m_isInAuction && v.equals(Boolean.TRUE)) {
        			m_log.add("b=a ON/OFF can't be enabled during auction time");
        		} else {
        			o.m_baOnOff =(Boolean) v;
        		}
        	}
			break;
		case NA_ONOFF:
			if (o.m_activate) {
        		if (m_log != null) {
        			m_log.add("N/A ON/OFF can only change in inactive status! Please OFF the spreader first");
        		}
        	} else {
        		if (o.m_isInAuction && v.equals(Boolean.TRUE)) {
        			m_log.add("N/A ON/OFF can't be enabled during auction time");
        		} else {
        			o.m_naOnOff =(Boolean) v;
        		}
        	}
			break;
		case OrderManager.BASE_DIFF:
			if (o.m_activate) {
        		if (m_log != null) {
        			m_log.add("Base Diff can only change in inactive status! Please OFF the spreader first");
        		}
        	} else {
        		o.m_baseDiff = Double.parseDouble(v.toString());
        	}
			break;
		case OrderManager.HEDGE_DIFF:
			if (o.m_activate) {
        		if (m_log != null) {
        			m_log.add("Hedge Diff can only change in inactive status! Please OFF the spreader first");
        		}
        	} else {
        		o.m_hedgeDiff = Double.parseDouble(v.toString());
        	}
			break;
		case IS_TRADE_PHASE:
			if (o.m_activate) {
				if (m_log != null) {
					m_log.add("Trade Phase can only change in inactive status! Please OFF the spreader first");
				}
			} else {
           		if (o.m_isInAuction && v.equals(Boolean.TRUE)) {
        			m_log.add("Trade Phase can't be enabled during auction time");
        		} else {
        			o.m_tradePhaseCheck = (Boolean) v;
        		}
			}
			break;
		case IS_IN_AUCTION:
			if (o.m_activate) {
				if (m_log != null) {
					m_log.add("Auction ON/OFF can only change in inactive status! Please OFF the spreader first");
				}
			} else {
				o.m_isInAuction = (Boolean) v;
				if (o.m_isInAuction) {
					o.m_baOnOff = false;
					o.m_naOnOff = false;
					o.m_tickOnOff = false;
					o.m_tradePhaseCheck = false;
				} else {
					o.m_baOnOff = true;
					o.m_naOnOff = true;
					o.m_tickOnOff = true;
					o.m_tradePhaseCheck = true;
				}
			}
			break;
		case AUCTION_TIME:
			if (o.m_activate) {
				if (m_log != null) {
					m_log.add("Trade Phase can only change in inactive status! Please OFF the spreader first");
				}
			} else {
				o.m_auctionTime = (Date) v;
			}
//			long kk  = o.m_auctionTime.getHours()*3600 + o.m_auctionTime.getMinutes()*60 + o.m_auctionTime.getSeconds();
//			Calendar cale = Calendar.getInstance();
//			cale.clear();
//			cale.setTimeInMillis(System.currentTimeMillis());
//			long curTime = cale.get(Calendar.HOUR_OF_DAY) * 3600 + cale.get(Calendar.MINUTE)*60 + cale.get(Calendar.SECOND);
//			System.out.println(kk + "  " + curTime);
			break;
		case AUCTION_OFFSET:
			if (o.m_activate) { 
				if (m_log != null) {
					m_log.add("Auction Offset can only change in inactive status! Please OFF the spreader first");
				}				
			} else {
				o.m_auctionOffset = (Double) v;
			}
	    default:
			break;
		}
		fireTableDataChanged();
//		System.out.println("v is " + v + " o.m is " + o.m_activate);
	}

	public String getColumnName(int c) {
		switch(c) {
		case OrderManager.BASE_SYM:
			return "Symbol";
		case OrderManager.EXCHANGE:
			return "Exchange";
		case OrderManager.BASE_SIZE:
			return "Size";
		case OrderManager.BASE_DIFF:
			return "Base Diff";
		case OrderManager.HEDGE_SYM:
			return "Hedge Symbol";
		case OrderManager.HEDGE_EXCHANGE:
			return "Hedge Exchange";
		case OrderManager.HEDGE_SIZE:
			return "Hedge Size";
		case OrderManager.HEDGE_DIFF:
			return "Hedge Diff";
		case OrderManager.MIN_STOCK_SIZE:
			return "Min Size";
		case OrderManager.LOW_SPREAD:
			return "Low Spread";
		case OrderManager.HIGH_SPREAD:
			return "High Spread";
		case OrderManager.BASE_STATE:
			return "Base State";
		case OrderManager.HEDGE_STATE:
			return "Hedge State";
		case OrderManager.ON_OFF:
			return "Eye ON/OFF";
		case OrderManager.DELETE:
			return "Delete";
		case OrderManager.BASE_POSITION:
			return "Base Position";
		case OrderManager.HEDGE_POSITION:
			return "Hedge Position";
		case TICK_STOP:
			return "Tick ON/OFF";
		case BA_ONOFF:
			return "b=a ON/OFF";
		case NA_ONOFF:
			return "N/A ON/OFF";
		case IS_TRADE_PHASE:
			return "Trade Phase";
		case IS_IN_AUCTION:
			return "Auction ON/OFF";
		case AUCTION_TIME:
			return "Auction Time";
		case AUCTION_OFFSET:
			return "Auction Offset";
	    default:
				return null;						
		}
	}

	public boolean isCellEditable(int r, int c)
	{
		OrderInfo orderInfo = (OrderInfo)m_allData.get(r);  
		if ( ((Boolean)orderInfo.getValue(OrderManager.ON_OFF)) == true){
			return c==OrderManager.ON_OFF;
		}
		
		return (c == BASE_SIZE || c==BASE_DIFF || c == HEDGE_SIZE || c == HEDGE_DIFF
				|| c == MIN_STOCK_SIZE || c == LOW_SPREAD || c == HIGH_SPREAD || c == ON_OFF ||
				c == DELETE || c == TICK_STOP || c==BA_ONOFF || c == NA_ONOFF || 
				c == IS_TRADE_PHASE || c == AUCTION_TIME || c == IS_IN_AUCTION || c == AUCTION_OFFSET
				);
	}
	
	void setLog(TextPanel log)
	{
		m_log = log;
	}
	
	public void reset()
	{
        m_allData.clear();
        m_symMap.clear();
    }
/*	
	public void setApi(ClientAPI c)
	{
		client = c;
	}
*/	
	public void panicTriggered(){
		int size = m_allData.size();
		for( int i=0; i<size; i++){
			m_allData.get(i).panic();
		}
		
		fireTableDataChanged();
	}
	
	
	public void addOrder(OrderInfo o)
	{
		
		m_allData.add(o);
		m_symMap.put(o.m_symbol, o);
		m_symMap.put(o.m_hedgeSymbol, o);
//		client.addQuoteListener(o.m_symbol,o.m_exchange,false, this);
//		client.addQuoteListener(o.m_hedgeSymbol, o.m_hedgeExchange, false, this);
//		m_BaseOrderMap.put(o.m_symbol+"."+ o.m_exchange, o);
//		m_HedgeOrderMap.put(o.m_hedgeSymbol+"."+ o.m_hedgeExchange, o);
		fireTableDataChanged();
	}

	@Override
	public void positionChanged(Position netPos) {
		// TODO Auto-generated method stub
		
		System.out.println( netPos.getSymbol() + "  " + netPos.getNetPosition() );
		OrderInfo o = m_symMap.get( netPos.getSymbol() );
		if ( o != null){
			o.positionChanged( netPos );
		}
		
		fireTableDataChanged();
	}

}
